/**
 * <vendor>
 *  Copyright 2009 Quanben Tech.
 * </vendor>
 */

using System;
using System.Collections.Generic;
using QSharp.String.Compiler;


namespace QSharp.String.Rex
{
    /**
     * <remarks>
     *  It is used for back-referencing
     * </remarks>
     */
    public class TagTracker : ICloneable
    {
        public Stack<TokenStream.Position> Start = new Stack<TokenStream.Position>();
        public TokenStream.Position End = null;

        public void BindStart(TokenStream.Position p)
        {
            if (End != null)
            {
                End = null;
                Start.Pop();
            }
            Start.Push(p);
        }

        public void BindEnd(TokenStream.Position p)
        {
            if (End == null)
            {
                if (Start.Count == 0)
                {
                    throw new InvalidOperationException();
                }
            }
            else
            {
                if (Start.Count <= 1)
                {
                    throw new InvalidOperationException();
                }
                Start.Pop();
            }
            End = p;
        }

        public void Set(TagTracker tag)
        {
            this.End = tag.End;
            this.Start = tag.Start;
        }

        public Object Clone()
        {
            TagTracker res = new TagTracker();
            res.End = this.End;

            TokenStream.Position[] temp = this.Start.ToArray();
            int i;
            for (i = this.Start.Count - 1; i >= 0; i--)
            {
                /**
                 * <remarks>
                 *  clone is necessary since popped-out position is referenced by
                 *  the active stream being parsed
                 * </remarks>
                 */
                res.Start.Push(temp[i].Clone() as TokenStream.Position);
            }

            return res;
        }

        public override string ToString()
        {
            return "Tag[" + this.GetHashCode() + "]";
        }

    }   /* class TagTracker */

    public class TagCreator
    {
        public TagTracker Tracker = null;
        public bool Closed = false;
    }

    public class TagMpper : Dictionary<string, TagCreator>
    {
        public new TagCreator this[string s]
        {
            get
            {
                if (this.ContainsKey(s))
                {
                    return base[s];
                }
                else
                {
                    return null;
                }
            }

            set
            {
                base[s] = value;
            }
        }
    }   /* class TagMapper */

}   /* namespace QSharp.String.Rex */
